//
//  UIView+JJExtension.swift
//  JJToolSwift
//
//  Created by heihei on 2024/5/8.
//

import Foundation

public struct YDRectCorner {
    var topLeft: CGFloat
    var topRight: CGFloat
    var bottomLeft: CGFloat
    var bottomRight: CGFloat
    // 创建四个角不同半径大小的圆角结构体
    public init(topLeft: CGFloat = 0, topRight: CGFloat = 0, bottomLeft: CGFloat = 0, bottomRight: CGFloat = 0) {
        self.topLeft = topLeft
        self.topRight = topRight
        self.bottomLeft = bottomLeft
        self.bottomRight = bottomRight
    }
    // 创建四个角相同半径大小的圆角结构体
    public init(all cornerRadius: CGFloat) {
        self.topLeft = cornerRadius
        self.topRight = cornerRadius
        self.bottomLeft = cornerRadius
        self.bottomRight = cornerRadius
    }
}

public extension UIView {
    
    private static var blockKey = "UITapgestureBlockKey"

    /// 为View添加UITapGestureRecognizer事件
    /// - Parameters:
    ///   - handler: 点击回调
    /// - Returns: UITapGestureRecognizer
    @discardableResult
    func addTap(handler: @escaping ((_ sender: UITapGestureRecognizer) -> Void)) -> UITapGestureRecognizer {
        self.isUserInteractionEnabled = true
        let target = _UITapgestureBlockTarget(handler: handler)
        objc_setAssociatedObject(self, &UIView.blockKey, target, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        let tap = UITapGestureRecognizer(target: target, action: #selector(_UITapgestureBlockTarget.invoke(_:)))
        self.addGestureRecognizer(tap)
        return tap
    }

    private class _UITapgestureBlockTarget {
        private var handler: (_ sender: UITapGestureRecognizer) -> Void
        init(handler: @escaping (_ sender: UITapGestureRecognizer) -> Void) {
            self.handler = handler
        }
        @objc func invoke(_ sender: UITapGestureRecognizer) {
            handler(sender)
        }
    }

    /// 左边值
    var left: CGFloat {
        get {
            return frame.origin.x
        }
        set {
            frame = CGRect(x: newValue, y: frame.origin.y, width: frame.width, height: frame.height)
        }
    }
    /// 右边值
    var right: CGFloat {
        get {
            return frame.origin.x + frame.size.width
        }
        set {
            frame = CGRect(x: newValue - frame.size.width, y: frame.origin.y, width: frame.width, height: frame.height)
        }
    }
    /// 上边值
    var top: CGFloat {
        get {
            return frame.origin.y
        }
        set {
            frame = CGRect(x: frame.origin.x, y: newValue, width: frame.width, height: frame.height)
        }
    }
    /// 下边值
    var bottom: CGFloat {
        get {
            return frame.origin.y + frame.size.height
        }
        set {
            frame = CGRect(x: frame.origin.x, y: newValue - frame.size.height, width: frame.width, height: frame.height)
        }
    }
    /// 宽度值
    var width: CGFloat {
        get {
            return frame.width
        }
        set {
            frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: newValue, height: frame.height)
        }
    }
    /// 高度值
    var height: CGFloat {
        get {
            return frame.height
        }
        set {
            frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.width, height: newValue)
        }
    }
    
    /// 中心横坐标值
    var centerX: CGFloat {
        get {
            return center.x
        }
        set {
            center = CGPoint(x: newValue, y: center.y)
        }
    }
    
    /// 中心纵坐标值
    var centerY: CGFloat {
        get {
            return center.y
        }
        set {
            center = CGPoint(x: center.x, y: newValue)
        }
    }
    
    /// 大小值
    var size: CGSize {
        get {
            return frame.size
        }
        set {
            frame.size = newValue
        }
    }
    
    // 边框和圆角相关
    
    /// 单实线样式
    ///
    /// - top: 顶部
    /// - right: 右边
    /// - bottom: 底部
    /// - left: 左边
    /// - all: 边框
    enum BorderEdge {
        case top, right, bottom, left, all
    }

    /// 圆角边框类型
    ///
    /// - none: 不显示边框
    /// - solid: 实线[width:线宽, color:线条颜色,]
    /// - dash: 虚线[width:线宽, color:线条颜色, pattern:样式]
    enum BorderType {
        /// 不显示边框
        case none
        /// 实线[width:线宽, color:线条颜色,]
        case solid(width: CGFloat, color: UIColor)
        /// 虚线[width:线宽, color:线条颜色, pattern:样式]
        case dash(width: CGFloat, color: UIColor, pattern: [NSNumber]?)
    }
    
    /// 给view添加边框
    ///
    /// - Parameter edge: 给哪一条边加边框
    /// - Parameter border: 边框样式
    func addBorder(edge: BorderEdge = .all, border: BorderType) {
        if case .none = border {
            return
        }
        let layer = CAShapeLayer()
        layer.frame = bounds
        layer.fillColor = UIColor.clear.cgColor
        switch border {
        case let .solid(width, color):
            layer.lineWidth = width
            layer.strokeColor = color.cgColor
        case let .dash(width, color, pattern):
            layer.lineWidth = width
            layer.strokeColor = color.cgColor
            layer.lineCap = CAShapeLayerLineCap(rawValue: "round")
            layer.lineDashPattern = pattern
        default:
            break
        }
        var bezierPath = UIBezierPath()
        switch edge {
        case .top:
            bezierPath.move(to: .zero)
            bezierPath.addLine(to: CGPoint(x: width, y: 0))
        case .right:
            bezierPath.move(to: CGPoint(x: width, y: 0))
            bezierPath.addLine(to: CGPoint(x: width, y: height))
        case .bottom:
            bezierPath.move(to: CGPoint(x: 0, y: height))
            bezierPath.addLine(to: CGPoint(x: width, y: height))
        case .left:
            bezierPath.move(to: .zero)
            bezierPath.addLine(to: CGPoint(x: 0, y: height))
        case .all:
            bezierPath = UIBezierPath(rect: bounds)
        }
        layer.path = bezierPath.cgPath
        self.layer.addSublayer(layer)
    }

    /// 指定位置切圆角
    ///
    /// - Parameters:
    ///   - corners: 需要切的角
    ///   - cornerRadii: 圆角半径
    ///   - border: 圆角边框类型 BorderType，默认不显示边框
    func bezierCorner(corners: UIRectCorner, cornerRadii: CGSize, border: BorderType = .none) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: cornerRadii)
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = maskPath.cgPath
        layer.mask = maskLayer
        if case .none = border {
            return
        }
        let layer = CAShapeLayer()
        layer.frame = bounds
        layer.fillColor = UIColor.clear.cgColor
        layer.path = maskPath.cgPath
        switch border {
        case let .solid(width, color):
            layer.lineWidth = width
            layer.strokeColor = color.cgColor
        case let .dash(width, color, pattern):
            layer.lineWidth = width
            layer.strokeColor = color.cgColor
            layer.lineCap = CAShapeLayerLineCap(rawValue: "round")
            layer.lineDashPattern = pattern
        default:
            break
        }
        self.layer.addSublayer(layer)
    }
    
    /// 同时给不同的角切不同半径的圆角
    /// - Parameters:
    ///   - corners: 切圆角的结构体
    ///   - frame: 坐标
    func addCorner(_ corners: YDRectCorner, frame: CGRect? = nil) {
        let rect: CGRect = frame ?? self.bounds
        // 绘制路径
        let path = CGMutablePath()
        let topLeftRadius = corners.topLeft
        let topLeftCenter = CGPoint(x: rect.minX + topLeftRadius, y: rect.minY + topLeftRadius)
        path.addArc(center: topLeftCenter, radius: topLeftRadius, startAngle: Double.pi, endAngle: Double.pi * 1.5, clockwise: false)
        let topRightRadius = corners.topRight
        let topRightCenter = CGPoint(x: rect.maxX - topRightRadius, y: rect.minY + topRightRadius)
        path.addArc(center: topRightCenter, radius: topRightRadius, startAngle: Double.pi * 1.5, endAngle: Double.pi * 2, clockwise: false)
        let bottomRightRadius = max(corners.bottomRight, 0)
        let bottomRightCenter = CGPoint(x: rect.maxX - bottomRightRadius, y: rect.maxY - bottomRightRadius)
        path.addArc(center: bottomRightCenter, radius: bottomRightRadius, startAngle: 0, endAngle: Double.pi * 0.5, clockwise: false)
        let bottomLeftRadius = max(corners.bottomLeft, 0)
        let bottomLeftCenter = CGPoint(x: rect.minX + bottomLeftRadius, y: rect.maxY - bottomLeftRadius)
        path.addArc(center: bottomLeftCenter, radius: bottomLeftRadius, startAngle: Double.pi * 0.5, endAngle: Double.pi, clockwise: false)
        path.closeSubpath()
        // 给layer添加遮罩
        let layer = CAShapeLayer()
        layer.path = path
        self.layer.mask = layer
    }

    /// UIView生成指定区域image
    ///
    /// - Parameters:
    ///   - rect: 指定生成区域，默认就是UIView的截图
    func toImage(rect: CGRect? = nil) -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: rect ?? bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
    
    /// 从nib加载view
    /// - Returns: 返回view
    static func loadFromNib() -> UIView {
        let temp = Bundle.main.loadNibNamed(String(describing: Self.self), owner: nil, options: nil)?.first
        return temp as! UIView
    }
}
